深拷贝与浅拷贝
chenpeng 2020-11-30 JS API
区分浅拷贝与深拷贝:假设 B 复制了 A,如果修改 B,A 也发生变化,就是浅拷贝;如果 A 没有发生变化,就是深拷贝
# 实现浅拷贝
1.for...in 循环赋值(只能拷贝第一层)
function simpleCopy(obj1) {
let obj2 = Array.isArray(obj1) ? [] : {};
for(let k in obj1){
if(obj1.hasOwnProperty(k)){
obj2[k] = obj1[k];
}
}
return obj2;
}
let obj1 = {
a: 1,
b: 2,
c: {
d: 3
}
};
let obj2 = simpleCopy(obj1);
obj2.a = 3;
obj2.c.d = 4;
console.log(obj1.a); // 1
console.log(obj1.c.d); // 4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2.Object.assign
let obj2 = Object.assign(obj1);
obj2.a = 3;
obj2.c.d = 4;
console.log(obj1.a); // 3
console.log(obj1.c.d); // 4
1
2
3
4
5
2
3
4
5
3.直接用 = 赋值
let obj2 = obj1;
obj2.a = 3;
obj2.c.d = 4;
console.log(obj1.a); // 3
console.log(obj1.c.d); // 4
1
2
3
4
5
2
3
4
5
# 实现深拷贝
1.递归拷贝所有层级属性
const objTypes = ['String', 'Number', 'Boolean', 'RegExp', 'Date']
/**
* 深拷贝,支持数组、正则、函数
* 利用WeakMap解决循环引用问题
* @param obj
* @param map
* @returns {*[]|any}
*/
function deepClone(obj, map = new WeakMap()) {
if (!obj || typeof obj !== 'object') {
return obj
}
if (map.has(obj)) {
return map.get(obj)
}
let objType = getObjType(obj)
if (objTypes.includes(objType)) {
return new obj.constructor(obj.valueOf())
}
let cloneObj = Array.isArray(obj) ? [] : {}
map.set(obj, cloneObj)
for (let key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
cloneObj[key] = deepClone(obj[key], map)
}
}
return cloneObj
}
function getObjType(obj) {
return Object.prototype.toString.call(obj).slice(8, -1)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
2.通过 JSON 对象来实现深拷贝
function deepCopy(obj1) {
let obj = JSON.stringify(obj1);
return JSON.parse(obj);
}
let obj2 = deepCopy(obj1);
1
2
3
4
5
2
3
4
5
缺点:
- 不能拷贝 function、正则、Symbol
- 循环引用报错
- 相同的引用会被重复拷贝
- 无法拷贝对象原型链上的属性和方法
3.通过jQuery的extend方法实现深拷贝
var array = [1,2,3,4];
var newArray = $.extend(true,[],array); // true为深拷贝,false为浅拷贝
1
2
2
4.lodash函数库实现深拷贝
let result = _.cloneDeep(test)
1